package com.hitqz.robot.biz.flow.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hitqz.robot.biz.flow.domain.json.xFlowRule.ChainInfo;
import com.hitqz.robot.biz.flow.domain.json.xFlowRule.Edge;
import com.hitqz.robot.biz.flow.domain.json.xFlowRule.Node;

import java.util.*;

/**
 * @author wengyx
 * @date 2023/09/08
 */
public class DagParser {

    public static String parseToExpression(List<Node> nodes, List<Edge> edges, String startNodeId, String endNodeId) {
        //构建节点map
        Map<String, Node> nodeMap = buildNodeMap(nodes, edges);
        //遍历图,生成表达式
        return parse(nodeMap, startNodeId);
    }

    public static Boolean checkNodes(List<Node> nodes, List<Edge> edges, ChainInfo chainInfo) {
        // 筛选掉群组
        nodes.removeIf(node -> "GROUP_NODE_RENDER_ID".equals(node.getRenderKey()));

        // 只有一个节点的情况
        if (nodes.size() == 1) {
            chainInfo.setStartNodeId(nodes.get(0).getId());
            chainInfo.setEndNodeId(nodes.get(0).getId());
            return true;
        }
        // 多个节点无连接的情况
        if (edges.isEmpty()) {
            return false;
        }
        // 正常情况
        Set<String> sourceNodeIdSet = new HashSet<>();
        Set<String> targetNodeIdSet = new HashSet<>();
        List<Node> endNodeList = new ArrayList<>();
        List<Node> startNodeList = new ArrayList<>();
        for (Edge edge : CollUtil.emptyIfNull(edges)) {
            sourceNodeIdSet.add(edge.getSource());
            targetNodeIdSet.add(edge.getTarget());
        }
        for (Node node : nodes) {
            if (!sourceNodeIdSet.contains(node.getId())) {
                endNodeList.add(node);
            }
            if (!targetNodeIdSet.contains(node.getId())) {
                startNodeList.add(node);
            }
        }
        if (endNodeList.size() != 1 || startNodeList.size() != 1) {
            return false;
        }
        chainInfo.setStartNodeId(startNodeList.get(0).getId());
        chainInfo.setEndNodeId(endNodeList.get(0).getId());
        return true;
    }

    private static Map<String, Node> buildNodeMap(List<Node> nodes, List<Edge> edges) {
        // 构建节点map,key为nodeId
        Map<String, Node> nodeMap = new HashMap<>();
        for (Node node : nodes) {
            nodeMap.put(node.getId(), node);
            node.setNextNodesIdList(new ArrayList<>());
            node.setPreNodesIdList(new ArrayList<>());
            //校验节点json参数
            if (CollUtil.isNotEmpty(node.getParamNames())){
                node.setParam(JSONUtil.parseObj(node.getParam()).toString());
            }else {
                node.setParam("");
            }
        }
        // 构建节点的nextNodesIdList 和 prevNodesIdList
        edges.forEach(edge -> {
            Node sourceNode = nodeMap.get(edge.getSource());
            sourceNode.getNextNodesIdList().add(edge.getTarget());
            Node targetNode = nodeMap.get(edge.getTarget());
            targetNode.getPreNodesIdList().add(edge.getSource());
        });
        return nodeMap;
    }

    private static String parse(Map<String, Node> nodeMap, String currNodeId) {
        Node currNode = nodeMap.get(currNodeId);
        String expression = "THEN(current,next)";
        String nodeExpression = StrUtil.isBlank(currNode.getParam()) ?  currNode.getName() :  currNode.getName()+".data('"+currNode.getParam()+"')";
        expression = expression.replace("current", nodeExpression);
        expression = expression.replace("next", parseNextNodes(nodeMap, currNode));
        expression = expression.replace(",)", ")").replace(",,", ",");
        return expression;

    }

    private static String parseNextNodes(Map<String, Node> nodeMap, Node currNode) {
        // 无下一节点
        if (CollUtil.isEmpty(currNode.getNextNodesIdList())) {
            return "";
        }
        // 一个下一节点
        if (currNode.getNextNodesIdList().size() == 1) {
            Node nextNode = nodeMap.get(currNode.getNextNodesIdList().get(0));
            //收敛节点
            String nodeExpression = StrUtil.isBlank(nextNode.getParam()) ?  nextNode.getName() :  nextNode.getName()+".data('"+nextNode.getParam()+"')";
            if (nextNode.getPreNodesIdList().size() > 1) {
                return "[" + nodeExpression + "," + nextNode.getId() + "]";
            }
            return nodeExpression + "," + parseNextNodes(nodeMap, nextNode);
        }
        // 多个下一节点
        StringBuilder s = new StringBuilder("(%0%");
        for (int i = 1; i < currNode.getNextNodesIdList().size(); i++) {
            s.append(",%").append(i).append("%");
        }
        String expression = "WHEN" + s + ")";
        for (int i = 0; i < currNode.getNextNodesIdList().size(); i++) {
            Node nextNode = nodeMap.get(currNode.getNextNodesIdList().get(i));
            String nodeExpression = StrUtil.isBlank(nextNode.getParam()) ?  nextNode.getName() :  nextNode.getName()+".data('"+nextNode.getParam()+"')";
            expression = expression.replace("%"+i+"%", nodeExpression + "," + parseNextNodes(nodeMap, nextNode));
        }
        //修改收敛节点的表达式  找[]中的表达式
        String convergentNode = ReUtil.get("\\[(.*?)\\]", expression, 0);
        expression = expression.replace(convergentNode, "");
        String[] split = convergentNode.replace("[", "").replace("]", "").split(",");
        currNode = nodeMap.get(split[1]);
        expression = expression + "," + split[0] + "," + parseNextNodes(nodeMap, currNode);
        return expression;
    }


}
